#include "segment_LED.h"

const uint8_t seg_LED_num[16] = {
    SEG_LED_SEGMENT_BITMASK_A | SEG_LED_SEGMENT_BITMASK_B | SEG_LED_SEGMENT_BITMASK_C | SEG_LED_SEGMENT_BITMASK_D | SEG_LED_SEGMENT_BITMASK_E | SEG_LED_SEGMENT_BITMASK_F, // 0
    SEG_LED_SEGMENT_BITMASK_B | SEG_LED_SEGMENT_BITMASK_C, // 1
    SEG_LED_SEGMENT_BITMASK_A | SEG_LED_SEGMENT_BITMASK_B | SEG_LED_SEGMENT_BITMASK_D | SEG_LED_SEGMENT_BITMASK_E | SEG_LED_SEGMENT_BITMASK_G, // 2
    SEG_LED_SEGMENT_BITMASK_A | SEG_LED_SEGMENT_BITMASK_B | SEG_LED_SEGMENT_BITMASK_C | SEG_LED_SEGMENT_BITMASK_D | SEG_LED_SEGMENT_BITMASK_G, // 3
    SEG_LED_SEGMENT_BITMASK_B | SEG_LED_SEGMENT_BITMASK_C | SEG_LED_SEGMENT_BITMASK_F | SEG_LED_SEGMENT_BITMASK_G, // 4
    SEG_LED_SEGMENT_BITMASK_A | SEG_LED_SEGMENT_BITMASK_C | SEG_LED_SEGMENT_BITMASK_D | SEG_LED_SEGMENT_BITMASK_F | SEG_LED_SEGMENT_BITMASK_G, // 5
    SEG_LED_SEGMENT_BITMASK_A | SEG_LED_SEGMENT_BITMASK_C | SEG_LED_SEGMENT_BITMASK_D | SEG_LED_SEGMENT_BITMASK_E | SEG_LED_SEGMENT_BITMASK_F | SEG_LED_SEGMENT_BITMASK_G, // 6
    SEG_LED_SEGMENT_BITMASK_A | SEG_LED_SEGMENT_BITMASK_B | SEG_LED_SEGMENT_BITMASK_C, // 7
    SEG_LED_SEGMENT_BITMASK_A | SEG_LED_SEGMENT_BITMASK_B | SEG_LED_SEGMENT_BITMASK_C | SEG_LED_SEGMENT_BITMASK_D | SEG_LED_SEGMENT_BITMASK_E | SEG_LED_SEGMENT_BITMASK_F | SEG_LED_SEGMENT_BITMASK_G, // 8
    SEG_LED_SEGMENT_BITMASK_A | SEG_LED_SEGMENT_BITMASK_B | SEG_LED_SEGMENT_BITMASK_C | SEG_LED_SEGMENT_BITMASK_D | SEG_LED_SEGMENT_BITMASK_F | SEG_LED_SEGMENT_BITMASK_G, // 9
    SEG_LED_SEGMENT_BITMASK_A | SEG_LED_SEGMENT_BITMASK_B | SEG_LED_SEGMENT_BITMASK_C | SEG_LED_SEGMENT_BITMASK_E | SEG_LED_SEGMENT_BITMASK_F | SEG_LED_SEGMENT_BITMASK_G, // A
    SEG_LED_SEGMENT_BITMASK_C | SEG_LED_SEGMENT_BITMASK_D | SEG_LED_SEGMENT_BITMASK_E | SEG_LED_SEGMENT_BITMASK_F | SEG_LED_SEGMENT_BITMASK_G, // B
    SEG_LED_SEGMENT_BITMASK_D | SEG_LED_SEGMENT_BITMASK_E | SEG_LED_SEGMENT_BITMASK_G, // C
    SEG_LED_SEGMENT_BITMASK_B | SEG_LED_SEGMENT_BITMASK_C | SEG_LED_SEGMENT_BITMASK_D | SEG_LED_SEGMENT_BITMASK_E | SEG_LED_SEGMENT_BITMASK_G, // D
    SEG_LED_SEGMENT_BITMASK_A | SEG_LED_SEGMENT_BITMASK_D | SEG_LED_SEGMENT_BITMASK_E | SEG_LED_SEGMENT_BITMASK_F | SEG_LED_SEGMENT_BITMASK_G, // E
    SEG_LED_SEGMENT_BITMASK_A | SEG_LED_SEGMENT_BITMASK_E | SEG_LED_SEGMENT_BITMASK_F | SEG_LED_SEGMENT_BITMASK_G, // F
};

/*
const SegmentLED_pin_map_stu_t mySegLED_pin_map_1[8] = {
    [SEG_LED_SEGMENT_A] = {
        .com = SEG_LED_COM1,
        .seg = SEG_LED_SEG1,
    },
    [SEG_LED_SEGMENT_B] = {
        .com = SEG_LED_COM1,
        .seg = SEG_LED_SEG2,
    },
    [SEG_LED_SEGMENT_C] = {
        .com = SEG_LED_COM3,
        .seg = SEG_LED_SEG2,
    },
    [SEG_LED_SEGMENT_D] = {
        .com = SEG_LED_COM4,
        .seg = SEG_LED_SEG2,
    },
    [SEG_LED_SEGMENT_E] = {
        .com = SEG_LED_COM3,
        .seg = SEG_LED_SEG1,
    },
    [SEG_LED_SEGMENT_F] = {
        .com = SEG_LED_COM2,
        .seg = SEG_LED_SEG1,
    },
    [SEG_LED_SEGMENT_G] = {
        .com = SEG_LED_COM2,
        .seg = SEG_LED_SEG2,
    },
    [SEG_LED_SEGMENT_DP] = {
        .com = SEG_LED_COM4,
        .seg = SEG_LED_SEG3,
    },
};

const SegmentLED_pin_map_stu_t mySegLED_pin_map_2[8] = {
    [SEG_LED_SEGMENT_A] = {
        .com = SEG_LED_COM1,
        .seg = SEG_LED_SEG1 + 2,
    },
    [SEG_LED_SEGMENT_B] = {
        .com = SEG_LED_COM1,
        .seg = SEG_LED_SEG2 + 2,
    },
    [SEG_LED_SEGMENT_C] = {
        .com = SEG_LED_COM3,
        .seg = SEG_LED_SEG2 + 2,
    },
    [SEG_LED_SEGMENT_D] = {
        .com = SEG_LED_COM4,
        .seg = SEG_LED_SEG2 + 2,
    },
    [SEG_LED_SEGMENT_E] = {
        .com = SEG_LED_COM3,
        .seg = SEG_LED_SEG1 + 2,
    },
    [SEG_LED_SEGMENT_F] = {
        .com = SEG_LED_COM2,
        .seg = SEG_LED_SEG1 + 2,
    },
    [SEG_LED_SEGMENT_G] = {
        .com = SEG_LED_COM2,
        .seg = SEG_LED_SEG2 + 2,
    },
    [SEG_LED_SEGMENT_DP] = {
        .com = SEG_LED_COM4,
        .seg = SEG_LED_SEG3 + 2,
    },
};

const SegmentLED_pin_map_stu_t mySegLED_pin_map_3[8] = {
    [SEG_LED_SEGMENT_A] = {
        .com = SEG_LED_COM1,
        .seg = SEG_LED_SEG1 + 4,
    },
    [SEG_LED_SEGMENT_B] = {
        .com = SEG_LED_COM1,
        .seg = SEG_LED_SEG2 + 4,
    },
    [SEG_LED_SEGMENT_C] = {
        .com = SEG_LED_COM3,
        .seg = SEG_LED_SEG2 + 4,
    },
    [SEG_LED_SEGMENT_D] = {
        .com = SEG_LED_COM4,
        .seg = SEG_LED_SEG2 + 4,
    },
    [SEG_LED_SEGMENT_E] = {
        .com = SEG_LED_COM3,
        .seg = SEG_LED_SEG1 + 4,
    },
    [SEG_LED_SEGMENT_F] = {
        .com = SEG_LED_COM2,
        .seg = SEG_LED_SEG1 + 4,
    },
    [SEG_LED_SEGMENT_G] = {
        .com = SEG_LED_COM2,
        .seg = SEG_LED_SEG2 + 4,
    },
    [SEG_LED_SEGMENT_DP] = {
        .com = SEG_LED_COM4,
        .seg = SEG_LED_SEG3 + 4,
    },
};

const SegmentLED_pin_map_stu_t mySegLED_pin_map_4[8] = {
    [SEG_LED_SEGMENT_A] = {
        .com = SEG_LED_COM1,
        .seg = SEG_LED_SEG1 + 6,
    },
    [SEG_LED_SEGMENT_B] = {
        .com = SEG_LED_COM1,
        .seg = SEG_LED_SEG2 + 6,
    },
    [SEG_LED_SEGMENT_C] = {
        .com = SEG_LED_COM3,
        .seg = SEG_LED_SEG2 + 6,
    },
    [SEG_LED_SEGMENT_D] = {
        .com = SEG_LED_COM4,
        .seg = SEG_LED_SEG2 + 6,
    },
    [SEG_LED_SEGMENT_E] = {
        .com = SEG_LED_COM3,
        .seg = SEG_LED_SEG1 + 6,
    },
    [SEG_LED_SEGMENT_F] = {
        .com = SEG_LED_COM2,
        .seg = SEG_LED_SEG1 + 6,
    },
    [SEG_LED_SEGMENT_G] = {
        .com = SEG_LED_COM2,
        .seg = SEG_LED_SEG2 + 6,
    },
    [SEG_LED_SEGMENT_DP] = {
        .com = SEG_LED_COM4,
        .seg = SEG_LED_SEG1,
    },
};
*/

const SegmentLED_pin_map_stu_t mySegLED_pin_map_1[8] = {
    [SEG_LED_SEGMENT_A] = {
        .com = SEG_LED_COM1,
        .seg = SEG_LED_SEG1,
    },
    [SEG_LED_SEGMENT_B] = {
        .com = SEG_LED_COM1,
        .seg = SEG_LED_SEG2,
    },
    [SEG_LED_SEGMENT_C] = {
        .com = SEG_LED_COM1,
        .seg = SEG_LED_SEG3,
    },
    [SEG_LED_SEGMENT_D] = {
        .com = SEG_LED_COM1,
        .seg = SEG_LED_SEG4,
    },
    [SEG_LED_SEGMENT_E] = {
        .com = SEG_LED_COM1,
        .seg = SEG_LED_SEG5,
    },
    [SEG_LED_SEGMENT_F] = {
        .com = SEG_LED_COM1,
        .seg = SEG_LED_SEG6,
    },
    [SEG_LED_SEGMENT_G] = {
        .com = SEG_LED_COM1,
        .seg = SEG_LED_SEG7,
    },
    [SEG_LED_SEGMENT_DP] = {
        .com = SEG_LED_COM1,
        .seg = SEG_LED_SEG8,
    },
};

const SegmentLED_pin_map_stu_t mySegLED_pin_map_2[8] = {
    [SEG_LED_SEGMENT_A] = {
        .com = SEG_LED_COM2,
        .seg = SEG_LED_SEG1,
    },
    [SEG_LED_SEGMENT_B] = {
        .com = SEG_LED_COM2,
        .seg = SEG_LED_SEG2,
    },
    [SEG_LED_SEGMENT_C] = {
        .com = SEG_LED_COM2,
        .seg = SEG_LED_SEG3,
    },
    [SEG_LED_SEGMENT_D] = {
        .com = SEG_LED_COM2,
        .seg = SEG_LED_SEG4,
    },
    [SEG_LED_SEGMENT_E] = {
        .com = SEG_LED_COM2,
        .seg = SEG_LED_SEG5,
    },
    [SEG_LED_SEGMENT_F] = {
        .com = SEG_LED_COM2,
        .seg = SEG_LED_SEG6,
    },
    [SEG_LED_SEGMENT_G] = {
        .com = SEG_LED_COM2,
        .seg = SEG_LED_SEG7,
    },
    [SEG_LED_SEGMENT_DP] = {
        .com = SEG_LED_COM2,
        .seg = SEG_LED_SEG8,
    },
};

const SegmentLED_pin_map_stu_t mySegLED_pin_map_3[8] = {
    [SEG_LED_SEGMENT_A] = {
        .com = SEG_LED_COM3,
        .seg = SEG_LED_SEG1,
    },
    [SEG_LED_SEGMENT_B] = {
        .com = SEG_LED_COM3,
        .seg = SEG_LED_SEG2,
    },
    [SEG_LED_SEGMENT_C] = {
        .com = SEG_LED_COM3,
        .seg = SEG_LED_SEG3,
    },
    [SEG_LED_SEGMENT_D] = {
        .com = SEG_LED_COM3,
        .seg = SEG_LED_SEG4,
    },
    [SEG_LED_SEGMENT_E] = {
        .com = SEG_LED_COM3,
        .seg = SEG_LED_SEG5,
    },
    [SEG_LED_SEGMENT_F] = {
        .com = SEG_LED_COM3,
        .seg = SEG_LED_SEG6,
    },
    [SEG_LED_SEGMENT_G] = {
        .com = SEG_LED_COM3,
        .seg = SEG_LED_SEG7,
    },
    [SEG_LED_SEGMENT_DP] = {
        .com = SEG_LED_COM3,
        .seg = SEG_LED_SEG8,
    },
};

const SegmentLED_pin_map_stu_t mySegLED_pin_map_4[8] = {
    [SEG_LED_SEGMENT_A] = {
        .com = SEG_LED_COM4,
        .seg = SEG_LED_SEG1,
    },
    [SEG_LED_SEGMENT_B] = {
        .com = SEG_LED_COM4,
        .seg = SEG_LED_SEG2,
    },
    [SEG_LED_SEGMENT_C] = {
        .com = SEG_LED_COM4,
        .seg = SEG_LED_SEG3,
    },
    [SEG_LED_SEGMENT_D] = {
        .com = SEG_LED_COM4,
        .seg = SEG_LED_SEG4,
    },
    [SEG_LED_SEGMENT_E] = {
        .com = SEG_LED_COM4,
        .seg = SEG_LED_SEG5,
    },
    [SEG_LED_SEGMENT_F] = {
        .com = SEG_LED_COM4,
        .seg = SEG_LED_SEG6,
    },
    [SEG_LED_SEGMENT_G] = {
        .com = SEG_LED_COM4,
        .seg = SEG_LED_SEG7,
    },
    [SEG_LED_SEGMENT_DP] = {
        .com = SEG_LED_COM4,
        .seg = SEG_LED_SEG8,
    },
};

void SEG_LED_show_num(struct SegmentLED_stu *led, SEG_LED_NUM_INDEX_t numx){
    if(numx < 0x0 || numx > 0xF){
        return; // 无效数字
    }

    for(uint8_t i = 0; i < 7; i++){
        if(seg_LED_num[numx] & (1 << i)){
            led->write_seg_pin(led, i, 0);
        } else {
            led->write_seg_pin(led, i, 1);
        }
    }
    
}

void SEG_LED_clean_num(struct SegmentLED_stu *led){

    for(uint8_t i = 0; i < 7; i++){
        led->write_seg_pin(led, i, 1);
    }
}

void SEG_LED_show_dot(struct SegmentLED_stu *led, uint8_t show_or_not){
    led->write_seg_pin(led, 7, !show_or_not);
}

uint32_t lcd_buf1 = 0;
uint32_t lcd_buf2 = 0;


uint8_t disp_map[4][8] = {
    [SEG_LED_COM1] = {
        [SEG_LED_SEG1] = 0 | 0x80,
        [SEG_LED_SEG2] = (8+0) | 0x80,
        [SEG_LED_SEG3] = (8+2) | 0x80,
        [SEG_LED_SEG4] = (8+3) | 0x80,
        [SEG_LED_SEG5] = 2 | 0x80,
        [SEG_LED_SEG6] = 1 | 0x80,
        [SEG_LED_SEG7] = (8+1) | 0x80,
        [SEG_LED_SEG8] = 16+3 | 0x80,
    },
    [SEG_LED_COM2] = {
        [SEG_LED_SEG1] = (16+0) | 0x80,
        [SEG_LED_SEG2] = (16+8+0) | 0x80,
        [SEG_LED_SEG3] = (16+8+2) | 0x80,
        [SEG_LED_SEG4] = (16+8+3) | 0x80,
        [SEG_LED_SEG5] = (16+2) | 0x80,
        [SEG_LED_SEG6] = (16+1) | 0x80,
        [SEG_LED_SEG7] = (16+8+1) | 0x80,
        [SEG_LED_SEG8] = 3,
    },
    [SEG_LED_COM3] = {
        [SEG_LED_SEG1] = 0,
        [SEG_LED_SEG2] = (8+0),
        [SEG_LED_SEG3] = (8+2),
        [SEG_LED_SEG4] = (8+3),
        [SEG_LED_SEG5] = 2,
        [SEG_LED_SEG6] = 1,
        [SEG_LED_SEG7] = (8+1),
        [SEG_LED_SEG8] = 16+3,
    },
    [SEG_LED_COM4] = {
        [SEG_LED_SEG1] = (16+0),
        [SEG_LED_SEG2] = (16+8+0),
        [SEG_LED_SEG3] = (16+8+2),
        [SEG_LED_SEG4] = (16+8+3),
        [SEG_LED_SEG5] = (16+2),
        [SEG_LED_SEG6] = (16+1),
        [SEG_LED_SEG7] = (16+8+1),
        [SEG_LED_SEG8] = (0+3) | 0x80,
    },
};

void my_write_xy(uint8_t x, uint8_t y, uint8_t state){
    if(x > 3 || y > 7){
        LOG_FMT(PRINT_DEBUG"Write LCD out of range: x%d, y%d\n", x, y);

        return ;
    }

    uint8_t offset_lcd_disp = disp_map[x][y] & 0x7F;

    if(disp_map[x][y] & 0x80){
        if(state){
            lcd_buf1 |= 0x00000001 << offset_lcd_disp;
        }else {
            lcd_buf1 &= ~(0x00000001 << offset_lcd_disp);
        }
    }else {
        if(state){
            lcd_buf2 |= 0x00000001 << offset_lcd_disp;
        }else {
            lcd_buf2 &= ~(0x00000001 << offset_lcd_disp);
        }
    }
}

void mySegLED_write_seg_pin(struct SegmentLED_stu *led, SEG_LED_SEGMENT_INDEX_t seg, uint8_t pin_state){
    if(seg >= 8){
        return; // 无效段
    }

    const SegmentLED_pin_map_stu_t *map = (led->segment_pin_map + seg);
    
    my_write_xy(map->com, map->seg, !pin_state);
}

void my_lcd_refresh(void){
    HAL_LCD_Write(&LCD_Handle, LCD_RAM_REGISTER0, lcd_buf1);
    HAL_LCD_Write(&LCD_Handle, LCD_RAM_REGISTER1, lcd_buf2);
}

void my_lcd_clean_all(void){
    lcd_buf1 = 0;
    lcd_buf2 = 0;
}
